package com.jacen.etl.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;


@SuppressWarnings("unchecked")
public class BaseDao<T> {
	protected Class<T> entityClass = null;

	public BaseDao() {
		entityClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	/**
	 * 新增
	 * @param Session
	 * @param t
	 */
	public void insert(Session session,T t) {
		session.save(t);
	}

	/**
	 * 修改
	 * @param Session
	 * @param t
	 */
	public void update(Session session,T t) {
		session.update(t);
	}

	/**
	 * 删除
	 * @param Session
	 * @param t
	 */
	public void delete(Session session,T t) {
		session.delete(t);
	}

	/**
	 * 删除（根据ID）
	 * @param Session
	 * @param id
	 */
	public void deleteById(Session session,Serializable id) {
		session.delete(getById(session,id));
	}
    
	/**
	 * 删除（根据属性值）
	 * @param Session
	 * @param propertyName
	 * @param propertyValue
	 */
	public int delEntityByKey(Session session,String propertyName, Object propertyValue)
			throws Exception {
		String hql = "delete from " + entityClass.getName() + " where 1 = 1 %s";
		hql = String.format(hql, "and " + propertyName + "= ?");
		return executeUpdate(session,hql, propertyValue);
	}
    
	/**
	 * 获取（根据ID值）
	 * @param Session
	 * @param id
	 */
	public T getById(Session session,Serializable id) {
		return (T) session.get(entityClass, id);
	}

	/**
	 * 获取（根据条件）
	 * @param Session
	 * @param hql
	 * @param objs
	 */
	public T getByCondition(Session session,String hql,Object... objs) {
		Query query = session.createQuery(hql);
		setQueryCondition(query, objs);

		List<T> resultList = (List<T>) query.list();
		if (resultList == null || resultList.size() == 0)
			return null;
		return resultList.get(0);
	}

	/**
	 * 获取（根据属性值）
	 * @param Session
	 * @param propertyName
	 * @param propertyValue
	 */
	public T getEntityByKey(Session session,String propertyName, Object propertyValue) {
		String hql = "from " + entityClass.getName() + " where 1 = 1 %s";
		hql = String.format(hql, "and " + propertyName + "= ?");
		return getByCondition(session,hql, propertyValue);
	}
    
	/**
	 * 判断实体是否存在（根据属性值）
	 * @param Session
	 * @param propertyName
	 * @param propertyValue
	 */
	public boolean existEntityByKey(Session session,String propertyName, Object propertyValue) {
		String hql = "select count(*) from " + entityClass.getName()
				+ " where 1 = 1 %s";
		hql = String.format(hql, "and " + propertyName + "= ?");
		return getCount(session,hql, propertyValue) > 0;
	}

	/**
	 * 获取所有实体
	 * @param Session
	 */
	public List<T> getAll(Session session) {
		String hql = "from " + entityClass.getName();
		Query query = session.createQuery(hql);
		return (List<T>) query.list();
	}

	/**
	 * 分页查询所有实体
	 * @param Session
	 * @param hql
	 * @param page
	 * @param size
	 * @param objs
	 */
	public List<T> getPage(Session session,String hql, int page, int size, Object... objs) {
		Query query = session.createQuery(hql);
		setQueryCondition(query, objs);

		query.setFirstResult((page - 1) * size).setMaxResults(size);
		return (List<T>) query.list();
	}
	
	/**
	 * 分页查询所有实体属性列表（根据sql语句）
	 * @param Session
	 * @param sql
	 * @param page
	 * @param size
	 * @param objs
	 */
	public List<Object[]> getPageBySQL(Session session,String sql, int page, int size,
			Object... objs) {
		SQLQuery query = session.createSQLQuery(sql);
		setQueryCondition(query, objs);

		query.setFirstResult((page - 1) * size).setMaxResults(size);
		return (List<Object[]>) query.list();
	}
    
	/**
	 * 根据条件查询实体总数
	 * @param Session
	 * @param hql
	 * @param objs
	 */
	public long getCount(Session session,String hql, Object... objs) {
		Query query = session.createQuery(hql);
		setQueryCondition(query, objs);

		return (Long) query.uniqueResult();
	}

	/**
	 * 根据条件查询实体总数（根据sql语句）
	 * @param Session
	 * @param sql
	 * @param objs
	 */
	public long getCountBySQL(Session session,String sql, Object... objs) {
		SQLQuery query = session.createSQLQuery(sql);
		setQueryCondition(query, objs);

		return ((BigDecimal) query.uniqueResult()).longValue();
	}

	/**
	 * 查询所有实体总数
	 * @param Session
	 */
	public Long getAllCount(Session session) {
		String hql = "select count(*) from " + entityClass.getName();
		Query query = session.createQuery(hql);
		return (Long) query.uniqueResult();
	}

	/**
	 * 判断实体是否存在（根据ID）
	 * @param Session
	 * @param id
	 */
	public boolean existById(Session session,Serializable id) {
		String hql = "select count(*) from " + entityClass.getName()
				+ " where id = ?";
		Query query = session.createQuery(hql);
		query.setParameter(0, id);
		Long count = (Long) query.uniqueResult();
		return count > 0;
	}
    
	/**
	 * 获取实体列表
	 * @param Session
	 * @param hql
	 * @param objs
	 */
	public List<T> getList(Session session,String hql, Object... objs) {
		Query query = session.createQuery(hql);
		setQueryCondition(query, objs);
		return (List<T>) query.list();
	}
   
	/**
	 * 获取实体属性列表（根据sql）
	 * @param Session
	 * @param sql
	 * @param objs
	 */
	public List<Object[]> getListBySQL(Session session,String sql, Object... objs) {
		SQLQuery query = session.createSQLQuery(sql);
		setQueryCondition(query, objs);
		return (List<Object[]>) query.list();
	}
   
	/**
	 * 删除所有
	 * @param Session
	 */
	public int delAll(Session session) {
		String hql = "delete from " + entityClass.getName();
		Query query = session.createQuery(hql);
		return query.executeUpdate();
	}

	/**
	 * 批量操作
	 * @param Session
	 * @param hql
	 * @param objs
	 */
	public int executeUpdate(Session session,String hql, Object... objs) throws Exception {
		Query query = session.createQuery(hql);
		setQueryCondition(query, objs);
		return query.executeUpdate();
	}

	/**
	 * 批量操作（根据sql）
	 * @param Session
	 * @param sql
	 * @param objs
	 */
	public int executeUpdateBySQL(Session session,String sql, Object... objs) throws Exception {
		SQLQuery query = session.createSQLQuery(sql);
		setQueryCondition(query, objs);

		return query.executeUpdate();
	}
    
	/**
	 * 批量新增实体
	 * @param Session
	 * @param entities
	 */
	public void batchInsertByHibernate(Session session,List<T> entities) {
		if (entities == null || entities.size() == 0)
			return;
		for (int i = 0; i < entities.size(); i++) {
			T t = entities.get(i);
			session.save(t);
			if (i % 500 == 0) {
				session.flush();
				session.clear();
			}
		}
	}

	/**
	 * 批量更新实体
	 * @param Session
	 * @param entities
	 */
	public void batchUpdateByHibernate(Session session,List<T> entities) {
		if (entities == null || entities.size() == 0)
			return;
		for (int i = 0; i < entities.size(); i++) {
			T t = entities.get(i);
			session.update(t);
			if (i % 500 == 0) {
				session.flush();
				session.clear();
			}
		}
	}

	protected void setQueryCondition(SQLQuery query, Object... objs) {
		for (int i = 0; i < objs.length; i++) {
			Object obj = objs[i];
			query.setParameter(i, obj);
		}
	}

	protected void setQueryCondition(Query query, Object... objs) {
		for (int i = 0; i < objs.length; i++) {
			Object obj = objs[i];
			query.setParameter(i, obj);
		}
	}
}
